<template>
  <form class="page page-directory-size">
    <h4 class="text-center">计算文件夹大小</h4>
    <fieldset class="fieldset-content">
      <legend>文件夹列表</legend>
      <div class="row-flex" align="center">
        <div class="row-flex-main text-left">共 {{filesList.length}} 个文件夹</div>
        <div class="row-flex-suffix">
          <button type="button" class="btn btn-link" @click="clearFilesList" title="清空">
            <i class="fa fa-trash-o"></i>
          </button>
        </div>
      </div>
      <div class="table-header" :style="thStyles">
        <table>
          <tbody>
            <tr>
              <th v-for="(v,i) in tableHeaders" :key="`th_${i}`" :style="{width: v.width}">
                {{v.label}}
              </th>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="table-body" @drop.prevent="filesDrop" @dragover.prevent>
        <table ref="table">
          <tbody>
            <tr v-for="(v,i) in myFilesList" :key="`file_${i}`">
              <template v-for="(item,index) in tableHeaders">
                <td :style="{width: item.width}" :key="`td_${i}_${index}`">
                  <button v-if="item.value==='action'" type="button" class="btn btn-link" @click="deleteFileItem(v.path)" title="删除">
                    <i class="fa fa-close"></i>
                  </button>
                  <span v-else-if="item.value==='size'">{{v[item.value] | formatFileSize}}</span>
                  <span v-else>{{v[item.value] || ''}}</span>
                </td>
              </template>
            </tr>
            <tr v-if="myFilesList.length===0" class="nodata-tr"><td>将待处理的文件夹拖动到此处</td></tr>
          </tbody>
        </table>
      </div>
      <div v-if="loadingCount > 0" class="mask">
        <x-loading></x-loading>
      </div>
    </fieldset>
    <div class="text-center" style="margin-top: .5em;">
      <x-button type="default" @click="clearFilesList" :loading="loadingCount > 0">清空列表</x-button>
      <x-button type="primary" @click="submitHandler" :loading="loadingCount > 0">开始计算</x-button>
    </div>
  </form>
</template>

<script>
const fs = global.require('fs')
const path = global.require('path')
// let {formatFileSize}  = global.$jstools || {}
let formatFileSize = (fileSize) => {
  fileSize = parseFloat(fileSize) || 0
  // 若参数不合法则直接return
  if (fileSize === 0) {
    return '0 B'
  }
  let unitArr = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
  let index = 0
  let result = ''
  index = Math.floor(Math.log(fileSize) / Math.log(1024))
  result = fileSize / Math.pow(1024, index)
  // 保留的小数位数
  let decimals = (index === 0 ? 0 : 2)
  result = result.toFixed(decimals) + ' ' + unitArr[index]
  return result
}

export default {
  name: 'directory-size',
  data () {
    return {
      filesList: [],
      tableHeaders: [
        {label: '文件名', value: 'fileName', width: '20%'},
        {label: '路径', value: 'path', width: '40%'},
        {label: '大小', value: 'size', width: '20%'},
        {label: '操作', value: 'action', width: '20%'},
      ],
      thStyles: {},
      loadingCount: 0
    }
  },
  computed: {
    filePathsList () {
      return this.filesList.map(v => v.path)
    },
    myFilesList () {
      let result = [...this.filesList]
      result.sort((a, b) => b.size - a.size)
      return result
    }
  },
  filters: {
    formatFileSize (val) {
      return formatFileSize(val)
    }
  },
  mounted () {
  },
  methods: {
    // 拖拽待处理文件夹
    filesDrop (e) {
      let filesList = e.dataTransfer.files
      if (!filesList) return
      for (let i = 0; i < filesList.length; i++) {
        let file = filesList[i]
        if (this.filePathsList.includes(file.path)) continue
        let fileStat = fs.statSync(file.path)
        if (!fileStat.isDirectory()) continue
        let fileName = path.basename(file.path) || file.name
        this.filesList.push({
          path: file.path,
          fileName,
          size: 0,
          status: ''
        })
      }
      this.checkScroll()
    },
    // 删除条目
    deleteFileItem (filePath) {
      let index = this.filePathsList.indexOf(filePath)
      this.filesList.splice(index, 1)
      this.checkScroll()
    },
    // 清空待处理文件
    clearFilesList () {
      this.filesList = []
      this.thStyles = {}
      this.loadingCount = 0
    },
    checkScroll () {
      this.$nextTick(() => {
        if (!this.$refs.table) return
        let tableHeight = this.$refs.table.clientHeight
        let tableParentHeight = this.$refs.table.parentNode.clientHeight
        if (tableHeight > tableParentHeight) {
          this.thStyles = {overflow: 'hidden scroll'}
        } else {
          this.thStyles = {overflow: 'hidden'}
        }
      })
    },
    // 批量处理
    submitHandler () {
      this.loadingCount++
      setTimeout(() => {
        this.filesList.forEach((v, i) => {
          let size = this.getItemSize(v.path)
          this.$set(this.filesList[i], 'size', size)
        })
        this.loadingCount--
        this.$toast('处理完成')
      }, 100)
    },
    getItemSize (filePath) {
      let result = 0
      // 检查源文件是否存在
      if (!fs.existsSync(filePath)) return result
      let stat = fs.statSync(filePath)
      if (stat.isDirectory()) {
        let files = fs.readdirSync(filePath)
        if (files.length) {
          files.forEach(v => {
            let size = this.getItemSize(path.join(filePath, v))
            result += (size || 0)
          })
        }
      } else {
        result = stat.size || 0
      }
      return result
    }
  }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";
.page-directory-size {
	display: flex;
	flex-direction: column;
  .row-flex-prefix {
    text-align: left;
  }
  fieldset {
    margin-top: 1em;
    .row-flex-prefix {width: 5em;}
  }
	.fieldset-content {
		height: 0;
		flex-grow: 1;
    position: relative;
    .table-header,
    .table-body {
      table {
        width: 100%;
        border: 1px solid @borderGrey;
        tr {height: 2em;}
        th, td {
          border: 1px solid @borderGrey;
          text-align: center;
          vertical-align: middle;
        }
        .nodata-tr {
          height: 100%;
          font-size: 16px;
          color: #999;
        }
      }
    }
    .table-body {
      height: calc(100% - 6.5em);
      overflow: auto;
      table {
        min-height: 100%;
      }
    }
    .mask {
      position: absolute;
      left: 15px;
      right: 15px;
      top: 0;
      bottom: 0;
      border-radius: 8px;
      background-color: rgba(255,255,255,.5);
      .flex-center;
    }
  }
}
</style>
